package com.veetao.api.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.veetao.api.dao.SysConfigDAO;
import com.veetao.api.model.AppClientAuth;
import com.veetao.api.model.AppClientInfo;
import com.veetao.api.model.ConfigChangeListener;
import com.veetao.api.service.MobileClientAppService;
import com.veetao.api.utils.McpUtils;

@Service
public class MobileClientAppServiceImpl implements MobileClientAppService,ConfigChangeListener {

	private static final Log logger = LogFactory.getLog(MobileClientAppServiceImpl.class);

	private Map<Integer, AppClientInfo> appIdAppInfoMap = null;

	private Map<Integer, List<AppClientAuth>> appAuthMap = null;

	@Autowired
	private SysConfigDAO appInfoDAO;

	public MobileClientAppServiceImpl() {
	}


	private void loadApp() {
		logger.info("loadApp start");
		long startTime = System.currentTimeMillis();
		List<AppClientInfo> appInfos = appInfoDAO.getAppList();

		Map<Integer, AppClientInfo> appIdAppInfoMap = new HashMap<Integer, AppClientInfo>();
		Map<Integer, List<AppClientAuth>> appAuthMap = new HashMap<Integer, List<AppClientAuth>>();
		
		List<AppClientAuth> allAuths = appInfoDAO.loadAllAuthorities();
		for(AppClientAuth auth : allAuths) {
			int appId = auth.getAppId();
			if(!appAuthMap.containsKey(appId)) {
				appAuthMap.put(appId, new ArrayList<AppClientAuth>());
			}
			appAuthMap.get(appId).add(auth);
		}
		
		for (AppClientInfo app : appInfos) {
			appIdAppInfoMap.put(app.getAppId(), app);
		}

		this.appAuthMap = appAuthMap;
		this.appIdAppInfoMap = appIdAppInfoMap;

		logger.info("loadApp end timecost:" + (System.currentTimeMillis() - startTime));
	}


	@Override
	public AppClientInfo getAppInfo(int appId) {
		if (appId == 0 || this.appIdAppInfoMap == null) {
			return null;
		}
		return this.appIdAppInfoMap.get(appId);
	}

	@Override
	public boolean isAllowedApiMethod(int appId, String methodName, String clientIP) {
		if (this.appAuthMap == null) {
			return false;
		}
		List<AppClientAuth> apiAuthList = this.appAuthMap.get(appId);
		if (apiAuthList == null) {
			return false;
		}
		for (AppClientAuth auth : apiAuthList) {
			if(auth.getForbidMethod() != null && McpUtils.leftMatch(methodName, auth.getForbidMethod())) {
				return false;
			}
			if (isClientIPAuthorized(clientIP, auth) && McpUtils.leftMatch(methodName, auth.getAuthMethod())) {
				return true;
			}
		}
		return false;
	}

	private boolean isClientIPAuthorized(String clientIP, AppClientAuth auth) {
		if(clientIP.equals("127.0.0.1")) {
			return true;
		}
		
		Set<String> authIPs = auth.getAuthIpSet();
		if (authIPs == null || authIPs.isEmpty()) {
			return true;
		}

		for (String authIP : authIPs) {
			if (McpUtils.leftMatch(clientIP, authIP)) {
				return true;
			}
		}

		return false;
	}

	public SysConfigDAO getAppInfoDAO() {
		return appInfoDAO;
	}

	public void setAppInfoDAO(SysConfigDAO appInfoDAO) {
		this.appInfoDAO = appInfoDAO;
	}

	@Override
	public void onConfigChange(SystemConfigService configService) {
		this.loadApp();
	}

}
